<?php


class Yapary_Webservice_Amazon_AmazonManager
{
	CONST ORDERBY_PRICE_ASC			= 'PRICE_ASC';
	CONST ORDERBY_PRICE_DESC		= 'PRICE_DESC';
	CONST ORDERBY_NAME_ASC			= 'NAME_ASC';
	CONST ORDERBY_NAME_DESC			= 'NAME_DESC';


	// Language:		['de', 'com', 'co.uk', 'ca', 'fr', 'co.jp', 'it', 'cn', 'es']
	// Categories:		['All','Apparel','Appliances','Automotive','Baby','Beauty','Blended','Books','Classical','DVD','Electronics','ForeignBooks','Grocery','HealthPersonalCare','HomeGarden','HomeImprovement','Jewelry','KindleStore','Kitchen','Lighting','Luggage','Marketplace','Magazines','MobileApps','MP3Downloads','Music','MusicalInstruments','MusicTracks','OfficeProducts','OutdoorLiving','Outlet','PCHardware','PetSupplies','Photo','Shoes','Software','SoftwareVideoGames','SportingGoods','Tools','Toys','VHS','Video','VideoGames','Watches']
	// ResponseGroup:	['Request','ItemIds','Small','Medium','Large','Offers','OfferFull','OfferSummary','OfferListings','PromotionSummary','PromotionDetails','VariationMinimum','VariationSummary','VariationMatrix','VariationOffers','Variations','TagsSummary','Tags','ItemAttributes','MerchantItemAttributes','Tracks','Accessories','EditorialReview','SalesRank','BrowseNodes','Images','Similarities','Subjects','Reviews','ListmaniaLists','SearchInside','PromotionalTag','SearchBins','AlternateVersions','Collections','RelatedItems','ShippingCharges','ShippingOptions'].
	private $accessKey			= NULL;
	private $secretKey			= NULL;
	private $country			= NULL;
	private $assiciateTag		= NULL;

	private $imageRequired		= false; // requires image in output

	private $lastError			= NULL;
	private $lastQuery			= NULL;
	private $arrLastResult		= NULL;
	private $maxProcess			= NULL;


	function __construct ($_accessKey, $_secretKey, $_country, $_associateTag) {
		$this->accessKey	= $_accessKey;
		$this->secretKey	= $_secretKey;
		$this->country		= $_country;
		$this->assiciateTag	= $_associateTag;
	}

	public function setImageRequired ($_required = true) {
		$this->imageRequired	= $_required;
	}


	private function awsRequest($_region, $_param, $_publicKey, $_privateKey, $associateTag=NULL, $_version='2011-08-01') {
		$host = 'webservices.amazon.'.$_region;
		$uri = '/onca/xml';

		$_param['Service']			= 'AWSECommerceService';
		$_param['AWSAccessKeyId']	= $_publicKey;
		$_param['Timestamp']		= gmdate('Y-m-d\TH:i:s\Z');
		$_param['Version']			= $_version;

		if ($associateTag !== NULL) {
			$_param['AssociateTag'] = $associateTag;
		}
		ksort($_param);

		$query = array(); // canonicalized query
		foreach ($_param as $param=>$value) {
			$param					= str_replace('%7E', '~', rawurlencode($param));
			$value					= str_replace('%7E', '~', rawurlencode($value));
			$query[]				= $param.'='.$value;
		}

		$query						= implode('&', $query);
		$signIn						= 'GET'."\n".$host."\n".$uri."\n".$query; // create the string to sign
		$signature					= base64_encode(hash_hmac('sha256', $signIn, $_privateKey, true)); // calculate HMAC with SHA256 and base64-encoding
		$signature					= str_replace('%7E', '~', rawurlencode($signature)); // encode the signature for the request
		$request					= 'http://'.$host.$uri.'?'.$query.'&Signature='.$signature; // create request
		$this->lastQuery			= $request;

		return $request;
	}


	/**
	 * Definiert die Maximale Anzahl parallel laufender Processe
	 * */
	public function setMaxProcess ($_maxProcess) {
		$this->maxProcess	= $_maxProcess;
	}


	/**
	 * Liefert die Fehlermeldung des letzten Aufrufs
	 * @return string
	 * */
	public function getLastError () {
		return $this->lastError;
	}

	/**
	 * Liefert die Suchbefehl des letzten Aufrufs
	 * @return string
	 * */
	public function getLastQuery () {
		return $this->lastQuery;
	}

	/**
	 * Liefert das Ergebnis der zuletzt durchgefuehrte Amazon Abfrage
	 * @return array
	 * */
	public function getListLastResult () {
		return $this->lastError;
	}


	public function findPopularItemList ($_arrKeyword, $_limit = NULL, $_orderBy = NULL, $_category = 'All', $_page = '1') {
		$arrTmp			= array();
		$arrResult		= array();
		$handles		= array();
		$mh				= curl_multi_init();
		$counter		= 0; // Counter fuer $_limit
		$oProcessHandlerImage	= new Yapary_Process_Handler();
		$oProcessHandlerQuery	= new Yapary_Process_Handler();
		$arrConnectionQuery		= array();

		foreach ($_arrKeyword as $key => $keyword) { // Vorbereitung, um parallelel URLs zu laden
			// http://stackoverflow.com/questions/6578832/how-to-convert-xml-into-array-in-php
			$arrParamAWS		= array(
										'Operation'     => 'ItemSearch',
										'Keywords'      => $keyword,
										'ResponseGroup' => 'Small,Images,Offers',
										'SearchIndex'   => $_category
								);
			$url				= $this->awsRequest($this->country, $arrParamAWS, $this->accessKey, $this->secretKey, $this->assiciateTag);
			$arrConnectionQuery[]	= new Yapary_Process_Connection($url);
		}

		// run processing to load search queries parallel
		$oProcessHandlerQuery->addList($arrConnectionQuery);
		$oProcessHandlerQuery->run($this->maxProcess);


		if (count($arrConnectionQuery)) { // Essentielle Elemente den vorbereiteten Daten extrahieren
			/* @var $oConnection Yapary_Process_Connection */
			foreach ($arrConnectionQuery as $key => $oConnection) {
				$arrVal						= json_decode(json_encode(simplexml_load_string($oConnection->getContent())), true);
				$this->lastError			= NULL;
				if (isset($arrVal['Items']['Request']['Errors'])) {
					$this->lastError		= $arrVal['Items']['Request']['Errors']['Error']['Code'];
					continue;
				}
				if (!isset($arrVal['Items']['Item']) || count($arrVal['Items']['Item']) == 0) { // Items not available
					continue;
				}
				if ( // Image required
					$this->imageRequired &&
					(!isset($arrVal['Item']['Item']['SmallImage']['URL']) || $arrVal['Item']['Item']['SmallImage']['URL'] == '')
				) {
					continue;
				}

				foreach ($arrVal['Items']['Item'] as $key => $val) {
		//			echo '<pre>'.print_r($response['Items']['Item'], true).'</pre>';
					if (is_array($val) && isset($val['ItemAttributes']['Title']) && isset($val['DetailPageURL']) && isset($val['OfferSummary']['LowestNewPrice'])) {
						if ($counter++ <= $_limit) { // As long as limit has not been reached
							$oAmazon			= new Yapary_Webservice_Amazon_Amazon($val);
							$arrResult[]		= $oAmazon;
							$oProcessHandlerImage->add($oAmazon->getConnection());
						}
					}
				}
			}
		}

		// run processing to load images parallel
		$oProcessHandlerImage->run($this->maxProcess);

		// Sorting
		if ($_orderBy != NULL) {
			$arrResult						= $this->orderBy($arrResult, $_orderBy);
		}

		return $arrResult;
	}


	private function orderBy ($_arrResult, $_orderBy) {
		/* @var $oEbay1 Yapary_Webservice_Ebay_Ebay */
		/* @var $oEbay2 Yapary_Webservice_Ebay_Ebay */
		switch ($_orderBy) {
			case self::ORDERBY_PRICE_ASC:
				usort($_arrResult, function($oEbay1, $oEbay2) {
					return $oEbay1->getPrice()->getPriceValue() - $oEbay2->getPrice()->getPriceValue();
				});
				break;
			case self::ORDERBY_PRICE_DESC:
				usort($_arrResult, function($oEbay1, $oEbay2) {
					return $oEbay2->getPrice()->getPriceValue() - $oEbay1->getPrice()->getPriceValue();
				});
				break;
			case self::ORDERBY_NAME_ASC:
				usort($_arrResult, function($oEbay1, $oEbay2) {
					return $oEbay1->getTitle() - $oEbay2->getTitle();
				});
				break;
			case self::ORDERBY_NAME_DESC:
				usort($_arrResult, function($oEbay1, $oEbay2) {
					return $oEbay2->getTitle() - $oEbay1->getTitle();
				});
				break;
			default:
				throw new Exception('Invalid value ORDERBY');
		}

		return $_arrResult;
	}


	/**
	 * Fuehrt eine Abfrage bei Amazon durch
	 * @result array[Yapary_Webservice_Amazon_Amazon]|NULL
	 * */
	public function findPopularItem ($_keywords, $_category = 'All', $_page = '1') {
		$arrResult	= array();

		// http://stackoverflow.com/questions/6578832/how-to-convert-xml-into-array-in-php
		$arrParamAWS		= array(
									'Operation'     => 'ItemSearch',
									'Keywords'      => $_keywords,
									'ResponseGroup' => 'Small,Images,Offers',
									'SearchIndex'   => $_category
							);
		$signedRequest	= $this->awsRequest($this->country, $arrParamAWS, $this->accessKey, $this->secretKey, $this->assiciateTag);
		$xml			= simplexml_load_string(file_get_contents($signedRequest));
		$json			= json_encode($xml);
		$response		= json_decode($json, true);
//		echo '<pre>'.print_r($response, true).'</pre>';


// 		$oAmazonEcsHandler	= new AmazonECS_Handler($this->accessKey, $this->secretKey, $this->country, $this->assiciateTag);
// 		//			$oAmazonEcsHandler->associateTag('marktreif06-20');
// 		$oAmazonEcsHandler->returnType(AmazonECS_Handler::RETURN_TYPE_ARRAY);
// 		$response			= $oAmazonEcsHandler->category($_category)->responseGroup('Small,Images,Offers')->optionalParameters(array('ItemPage' => $_page))->search($_keywords);

		$this->arrLastResult= $response;
		if (isset($response['Items']['Request']['Errors'])) {
			$this->lastError= $response['Items']['Request']['Errors']['Error']['Code'];
			return NULL;
		}

		$this->lastError	= NULL;
		if (!isset($response['Items']['Item']) || count($response['Items']['Item']) == 0) { // Items not available
			return $arrResult;
		}

		foreach ($response['Items']['Item'] as $key => $arrVal) {
//			echo '<pre>'.print_r($response['Items']['Item'], true).'</pre>';
			if (is_array($arrVal) && isset($arrVal['ItemAttributes']['Title']) && isset($arrVal['DetailPageURL']) && isset($arrVal['OfferSummary']['LowestNewPrice'])) {
				$arrResult[]	= new Yapary_Webservice_Amazon_Amazon($arrVal);
			}
		}

		return $arrResult;
	}


	/**
	 * Liefert anhand einer durchgefuehrten Abfrage (findXY...) die optimale Kategorien
	 * @result array[Yapary_Webservice_Amazon_Amazon]|NULL
	 * */
	public function getListCategory ($_arrResult) {
		$arrResult	= array();

// 		$url		= $this->getUrl('FindPopularItems', rawurlencode($_keywords), $_responseEncoding);
// 		$content	= file_get_contents($url);
// 		$arr		= json_decode($content, true);
		$arr		= $this->arrLastResult;

		if (isset($arr['Errors'])) {
			$this->lastError	= $arr['Errors'];
			return NULL;
		}

		$this->lastError	= NULL;
		if (isset($arr['Items']['Request']['Errors'])) {
			$this->lastError= $arr['Items']['Request']['Errors']['Error']['Code'];
			return $arrResult;
		}

		// Kategorien sammeln und Anzahl der Haeufigkeit zaehlen
		foreach ($arr['Items']['Item'] as $key => $arrVal) {
			if (isset($arrVal['ItemAttributes']) && isset($arrVal['ItemAttributes']['ProductGroup'])) {
				$tmp			= $arrVal['ItemAttributes']['ProductGroup'];
				$name			= utf8_decode(trim($tmp));

				if (isset($arrResult[$name])) {
					$i	= (int) $arrResult[$name];
					$arrResult[$name]	= $i+1;
				} else {
					$arrResult[$name]	= 1;
				}
			}
		}

		// Eintraege mit zu wenig Vorkommen entfernen
		$count	= count($arrResult);
		if ($count) {
			while (list($name, $sum) = each($arrResult)) {
				if ($arrResult[$name] <= 2) {
					unset($arrResult[$name]);
				}
			}
		}

//		rsort($arrResult);
		return $arrResult;
	}


}